#pragma once

class Client
{
public:
	
	Client(unsigned long address)
	{
		connector = new Connector<ServiceHandler, SOCK_Connector>(Reactor::instance());

		patient = new Patient(Reactor::instance());
		patientAddr = new INET_Addr(DEFAULT_PORT_PATIENT, address);   
		log = new Log(Reactor::instance());
		logAddr = new INET_Addr(DEFAULT_PORT_LOG, address);   
		alarm = new Alarm(Reactor::instance());
		alarmAddr = new INET_Addr(DEFAULT_PORT_ALARM, address);   
		
		stopWatch = new StopWatch();
	}
	
	void run(int clientType, bool asyncConnect = false)
	{
		switch (clientType)
		{
			case 1: // Patient
				connector->connect(patient, patientAddr, asyncConnect);
				break;

			case 2: // Log
				connector->connect(log, logAddr, asyncConnect);
				break;

			case 3: // Alarm
				connector->connect(alarm, alarmAddr, asyncConnect);
				break;
		}

		// Simulate generating events (Alarm, Log and Patient)
		while (1) {

			if (asyncConnect == true) {
				Reactor::instance()->handleEvents(10000);
				SimulateClient(clientType, patient, log, alarm);
			} else
			{
				SimulateClient(clientType, patient, log, alarm);
				Reactor::instance()->handleEvents(10000);
			}
		}
	}
	
	void runLoopTest(int clientType)
	{
		char buffer[SIZE_BIG];
	
		for (int i = 1; i < 3000; i++) {
			sprintf(buffer, "Client %d", i);
			stopWatch->start();
			switch (clientType)
			{
				case 1: // Patient
					connector->connect(patient, patientAddr);
					patient->getPatientInfo(buffer);
					break;

				case 2: // Log
					connector->connect(log, logAddr);
					log->saveLog(buffer);
					break;

				case 3: // Alarm
					connector->connect(alarm, alarmAddr);
					alarm->setAlarm(buffer);
					break;
			}
			Reactor::instance()->handleEvents(10000); // Wait max. 10 ms on select
			stopWatch->split(buffer);
			stopWatch->stop();
			connector->close();
		}
	    Sleep(100);
	}

	void SimulateClient(int clientType, Patient *patient, Log *log, Alarm *alarm)
	{
		char buffer[SIZE_BIG];

		switch (clientType)
		{
			case 1: // Patient
				printf("Enter CPR > ");
				scanf("%s", buffer);
				patient->getPatientInfo(buffer);
				break;

			case 2: // Log
				printf("Save log > ");
				scanf("%s", buffer);
				log->saveLog(buffer);
				break;

			case 3: // Alarm
				printf("Set alarm > ");
				scanf("%s", buffer);
				alarm->setAlarm(buffer);
				break;
		}
	}

private:
	StopWatch *stopWatch;
	Connector<ServiceHandler, SOCK_Connector> *connector;
	Patient *patient;
	INET_Addr *patientAddr;   
	Log *log;
	INET_Addr *logAddr;   
	Alarm *alarm;
	INET_Addr *alarmAddr;   
};


